import pandas as pd
import numpy as np
from statsmodels.stats.outliers_influence import variance_inflation_factor
from scipy.stats import pearsonr

""" import sys
sys.path.append('D:/gitee/python-script-new/papertools/') """

from paper_tool.papertools import r2
from paper_tool.papertools import common_functions

file_path = 'dest/20231204-163318_truncatedNew.xlsx'
sheet_name = 'sheet_test'


# 共线性或线性相关性：与前面提到的 factor_analyzer 库的警告类似，共线性或线性相关性在协方差矩阵中可能导致特征值接近或等于零，使矩阵不是正定的。
# 在这种情况下，你可以尝试进行数据预处理或使用其他因子分析方法。


# 相关性分析：使用相关系数来检测线性相关性。在Python中，你可以使用pandas库的corr()方法计算特征之间的相关系数。通常，皮尔逊相关系数用于测量线性相关性，其取值范围从-1到1。
# 相关系数接近1表示正相关，接近-1表示负相关，接近0表示无相关性。
def modify_data_to_reduce_correlation(dataset,corr_item):
    # dataset[corr_item['variable_1']],dataset[corr_item['variable_2']],]
    # correlation = corr_item['corr_coefficient']  # 初始相关性设为 1，进入循环
    data1 = dataset[corr_item['variable_1']] 
    data2 = dataset[corr_item['variable_2']] 
    correlation, _ = pearsonr(data1, data2)
    print(f" {corr_item['variable_1']}和 {corr_item['variable_2']}的相关系数 {correlation}")
    
    count = 0
    while abs(correlation) >= 0.8:
        # 调整 data2 的数据排序           
        numArrLength = len(data2)
        max_index = numArrLength //5
        # 调整的[数值对]会越来越多
        item_number = numArrLength //30      
        r2.generate_random_index_pairsAndExchange(data2,max_index = max_index,item_length = item_number)
        # 计算新的相关系数
        correlation, _ = pearsonr(data1, data2)
        count += 1
    
    print("\033[32m" + f"变量 {corr_item['variable_2']} 调整了 {count} 次, 新的皮尔逊相关系数{correlation:.2f}")
    return data2

def main_highly_correlated_reduce(file_path,sheet_origin_name,saveSheetName = 'highlyCorrelatedReduced',init_mean_sheet_name='Sheet1'):

    dataset = pd.read_excel(file_path, sheet_name=sheet_origin_name,)


    # 皮尔逊相关系数
    correlation_matrix = dataset.corr()

    # print('皮尔逊相关系数: ')
    # print(correlation_matrix)

    # 设定相关性阈值
    threshold = 0.8

    # 打印相关性系数大于0.8的相关变量名和系数
    print("Highly Correlated Variables:")
    correlated_variables = []  # 保存相关性大于0.8的变量名
    for i in range(len(correlation_matrix.columns)):
        for j in range(i + 1, len(correlation_matrix.columns)):
            corr_coefficient = abs(correlation_matrix.iloc[i, j])
            if corr_coefficient > threshold:
                variable1 = correlation_matrix.columns[i]
                variable2 = correlation_matrix.columns[j]
                print(f"{variable1} and {variable2}: {corr_coefficient:.2f}")

            # 仅将列名靠后的变量放入correlated_variables    
                correlated_variables.append({"variable_1": variable1, "variable_2": variable2, "corr_coefficient": corr_coefficient})      
    
    # 对相关性大于0.8的变量名进行去重
    # correlated_variables = np.unique(correlated_variables)

    if len(correlated_variables) > 0:
        # 重新生成数据的代码 !!!!!!!!!
        # 改进, 数据顺序局部调整, 2023-1203 
        print('数据顺序局部调整')
        oringinAverageData = pd.read_excel(file_path, sheet_name=init_mean_sheet_name)
        # 获取数据框中的第一行数据
        # mean_values = oringinAverageData.iloc[0].values

        # 统一为这些变量重新生成数据
        for corr_item_dict in correlated_variables:
            # 使用你的函数重新生成数据            
            """ meanVal = common_functions.get_first_cell(oringinAverageData,variable)
            print('meanVal ',meanVal)
            dataset[variable] = r2.generate_integersV1(meanVal) """
            # 对第二列数据进行局部顺序调换
            dataset[corr_item_dict['variable_2']] = modify_data_to_reduce_correlation(dataset,corr_item_dict)
        
        # 创建一个ExcelWriter对象，打开原始Excel文件以进行写入
        with pd.ExcelWriter(file_path, engine='openpyxl', mode='a') as writer:
            # 将修改后的数据写入新的工作表（这里使用名为'highlyCorrelatedReduce'的工作表）
            dataset.to_excel(writer, sheet_name=saveSheetName, index=False)

        print("Data generated and saved to ", saveSheetName)
    else:
        print("\033[35m" + "Good, 变量相关性正常!!" + "\033[0m")
        
    
    # 方差膨胀因子（VIF）：VIF是一种用于检测共线性的指标。它测量了一个特征与其他特征之间的线性关系。通常，VIF小于10被认为是低共线性，而大于10可能表示存在共线性。
    # 你可以使用Python中的统计工具包（如statsmodels）来计算VIF。

    # 如果VIF值较高，可能需要考虑删除其中一个相关性较强的特征。

    vif = pd.DataFrame()
    vif["Features"] = dataset.columns
    vif["VIF"] = [variance_inflation_factor(dataset.values, i) for i in range(dataset.shape[1])]

    print('\033[31m' +'方差膨胀因子: '+ '\033[0m')
    print(vif["VIF"])


if __name__ == "__main__":
    main_highly_correlated_reduce(file_path,sheet_name)
